#pragma once
#include "Common.hpp"
#include <fstream>
class Command
{
public:
    Command()
    {
        //命令白名单
        std::ifstream in(FILE_PATH);
        std::string line;
        if (!in.is_open())
        {
            LOG(FATAL, "load ArrowCommand.txt error!\n");
            exit(ARROW_COMMAND_ERROE);
        }
        while (std::getline(in, line))
        {
            LOG(DEBUG,"insert safe command done\n");
            _arrow_commands.insert(line);
        }
    }
    ~Command() {}
    bool is_SafeCmd(const std::string &cmdstr)
    {
        auto it = _arrow_commands.find(cmdstr);
        if(it != _arrow_commands.end()) return true;
        return false;
    }
    // 执行业务的函数
    std::string Excute(const std::string &cmdstr)
    {
        if(!is_SafeCmd(cmdstr)) return "unsafe command!\n";
        std::string ret;
        FILE *pf = popen(cmdstr.c_str(), "r");
        if(pf)
        {
            char buf[1024];
            while(fgets(buf,sizeof(buf),pf))
            {
                ret+=buf;
            }
            return ret.empty() ? "success!" : ret;
        }
        return "error!\n";
    }
    void ExcuteCommand(int sockfd, InetAddr addr)
    {
        while (true)
        {
            // 收client发送的信息==read数据
            char inbuf[1024];
            // 面向字节流recv
            ssize_t n = ::recv(sockfd, inbuf, sizeof(inbuf) - 1, 0);
            if (n > 0)
            {
                // 接收消息成功
                inbuf[n] = 0;
                LOG(INFO, "get a command from client %s,command: %s\n", addr.GetAddrStr().c_str(), inbuf);
                std::string echo_msg = Excute(inbuf);
                // TODO
                // 面向字节流send
                ::send(sockfd, echo_msg.c_str(), echo_msg.size(), 0);
            }
            else if (n == 0)
            {
                // client quit
                LOG(INFO, "client[%s] quit\n", addr.GetAddrStr().c_str());
                break;
            }
            else
            {
                LOG(ERROR, "read [%s] message error!\n", addr.GetAddrStr().c_str());
                break;
            }
        }
    }

private:
    std::set<std::string> _arrow_commands;
};